`timescale 1ns / 1ps

module axi_bram_write_test_128bit;

// 时钟和复位
reg clk;
reg reset_n;

// AXI Master接口信号
wire [31:0] awaddr;
wire [7:0] awlen;
wire [2:0] awsize;
wire [1:0] awburst;
wire awvalid;
reg awready;

wire [127:0] wdata;  // 改为128位
wire [15:0] wstrb;   // 改为16位
wire wlast;
wire wvalid;
reg wready;

reg [1:0] bresp;
reg bvalid;
wire bready;

// 用户接口信号
reg start;
reg read_write;
reg [31:0] addr;
reg [7:0] burst_len;
reg [2:0] burst_size;
reg [1:0] burst_type;
reg [127:0] write_data;  // 改为128位
reg write_data_valid;
wire write_data_ready;
wire [127:0] read_data;  // 改为128位
wire done;
wire error;

// BRAM接口信号
wire [11:0] bram_addr;
wire [127:0] bram_din;  // 改为128位
wire bram_we;
wire [127:0] bram_dout; // 改为128位

// 实例化AXI Master
axi_master #(
    .DATA_WIDTH(128),  // 改为128位
    .ADDR_WIDTH(32),
    .BURST_LEN_WIDTH(8)
) axi_master_inst (
    .clk(clk),
    .reset_n(reset_n),
    
    // AXI Write Address Channel
    .awaddr(awaddr),
    .awlen(awlen),
    .awsize(awsize),
    .awburst(awburst),
    .awvalid(awvalid),
    .awready(awready),
    
    // AXI Write Data Channel
    .wdata(wdata),
    .wstrb(wstrb),
    .wlast(wlast),
    .wvalid(wvalid),
    .wready(wready),
    
    // AXI Write Response Channel
    .bresp(bresp),
    .bvalid(bvalid),
    .bready(bready),
    
    // AXI Read Address Channel (未使用)
    .araddr(),
    .arlen(),
    .arsize(),
    .arburst(),
    .arvalid(),
    .arready(1'b0),
    
    // AXI Read Data Channel (未使用)
    .rdata(128'h0),
    .rresp(2'b00),
    .rlast(1'b0),
    .rvalid(1'b0),
    .rready(),
    
    // User interface
    .start(start),
    .read_write(read_write),
    .addr(addr),
    .burst_len(burst_len),
    .burst_size(burst_size),
    .burst_type(burst_type),
    .write_data(write_data),
    .write_data_valid(write_data_valid),
    .write_data_ready(write_data_ready),
    .read_data(read_data),
    .done(done),
    .error(error)
);

// 实例化BRAM (需要修改为128位宽度)
int8 int8 (
    .clka(clk),
    .ena(1'b1),
    .wea(bram_we),
    .addra(bram_addr),
    .dina(bram_din),
    .douta(bram_dout),
    .rsta(~reset_n)
);

// BRAM地址映射 (将AXI地址转换为BRAM地址)
assign bram_addr = awaddr[14:3];  // 128位对齐，除以16
assign bram_din = wdata;
assign bram_we = wvalid && wready;

// AXI响应信号
assign awready = 1'b1;  // 总是准备好接收地址
assign wready = 1'b1;   // 总是准备好接收数据
assign bresp = 2'b00;   // OKAY响应
assign bvalid = wlast && wvalid && wready;  // 最后一个数据时产生响应

// 时钟生成
initial begin
    clk = 0;
    forever #5 clk = ~clk;  // 100MHz时钟
end

// 从int8.coe文件中提取的测试数据 (前96个128位数据，每两个64位数据合并为一个128位)
reg [127:0] test_data [0:95];  // 192个64位数据合并为96个128位数据

initial begin
    // 从int8.coe文件中提取的数据，每两个64位数据合并为一个128位
    // 第1-2行合并
    test_data[0] = {64'h84f5191992b34329, 64'h25095ce6b539265b};
    test_data[1] = {64'h4941f3c57e7a942e, 64'h2253fc8678538ab6};
    test_data[2] = {64'hc459caff4d76f9b9, 64'h4856a66f33f6934e};
    test_data[3] = {64'h060561d6ef40a910, 64'h66f33088dafeef4a};
    test_data[4] = {64'h990c84ceb326c215, 64'h9484a9821b836412};
    test_data[5] = {64'h6b94cd360d0c50da, 64'h87680c463b37a009};
    test_data[6] = {64'hc67bc37d47d8b1f3, 64'hc3f49e8f945ff4da};
    test_data[7] = {64'hf5c2b8948d25f678, 64'hc354ebc03811ca91};
    test_data[8] = {64'h70afea4b088ac7b4, 64'hc86f65a6c1b6a00b};
    test_data[9] = {64'h93773cdc90fd933f, 64'h823ea75e80000000};
    test_data[10] = {64'hb9c3af671a688c30, 64'hd64241ccb2d3f9f6};
    test_data[11] = {64'h274191cf28ff75b8, 64'hcffbe0da358db47f};
    test_data[12] = {64'h49bd66365894ca30, 64'h717762af9087e062};
    test_data[13] = {64'hd87bb7cfd4e4fd41, 64'h69bd5662909eb865};
    test_data[14] = {64'h8998424daeb54307, 64'h429b0fa1e47651be};
    test_data[15] = {64'h6e8ec88968e7047b, 64'ha1bd6f44031b9bb1};
    test_data[16] = {64'h16d30a5f98a8276d, 64'hac10fd8e945441b6};
    test_data[17] = {64'hf722c0e33e7567e9, 64'hec924e3a564f8d57};
    test_data[18] = {64'hf1f8648da111e75a, 64'h9f44f5c69b31ece6};
    test_data[19] = {64'h7169795984b2d93f, 64'h8d01858b153dec6d};
    test_data[20] = {64'h1b2288f0032ac091, 64'h2456ec07dbff4a47};
    test_data[21] = {64'h262e2e3d80000000, 64'hf0e557023f0e4211};
    test_data[22] = {64'hd1c8a3a36f41c070, 64'h846af840d9d8dc7c};
    test_data[23] = {64'h2ad49af5f7f5f6d4, 64'h1102833d35fc87f8};
    test_data[24] = {64'hc5d821b2c3f57dc7, 64'h9fa98f434f69ed10};
    test_data[25] = {64'hb4c29d715842152b, 64'h412d0bc07b32db17};
    test_data[26] = {64'h5323041654701145, 64'he5d92bb4796ed5e2};
    test_data[27] = {64'h2bff319c0f7e6c3f, 64'h7d45d470c7d01f59};
    test_data[28] = {64'h1de0282351796ea7, 64'hb74d7413a8e4fc74};
    test_data[29] = {64'h49918eeae9e3ea74, 64'h7a8c15414b3f1b5c};
    test_data[30] = {64'h56e4d238c47c4563, 64'h97ba6e46f5b491f8};
    test_data[31] = {64'hcc55fb289f7bb8b5, 64'h861cd71b23e56da9};
    test_data[32] = {64'h0c4f7e52775b5a58, 64'h76105d98a2a69342};
    test_data[33] = {64'h28fcedf4abfc8143, 64'h1a7c1cf2e9c4aa3c};
    test_data[34] = {64'h821e61005ba78184, 64'h091187c18c5ccf54};
    test_data[35] = {64'h13091b00820e2d02, 64'h5a1ef75c5032968c};
    test_data[36] = {64'heb4234701b01d5d0, 64'h6f0b0f1ad6f90c03};
    test_data[37] = {64'he5b562eec8efb137, 64'h680673b0e1bf4309};
    test_data[38] = {64'h232d77b212ab089a, 64'h9b0daf3738cc56e4};
    test_data[39] = {64'h47632c0171b7d249, 64'h6286b0b394ae20ce};
    test_data[40] = {64'h3cccc4e95a203c8f, 64'h62b645de8c76beea};
    test_data[41] = {64'h9aa513c30c60fac6, 64'hae80c90e91af3681};
    test_data[42] = {64'h25d9fdfaf2282f30, 64'h1ba7cf9a2d24471b};
    test_data[43] = {64'h5b617dd19d1dc72a, 64'hbfa774b889c5395e};
    test_data[44] = {64'hafc1946dd6cee341, 64'h7ddae3880d1c4dbc};
    test_data[45] = {64'h70ae9d069691e3b6, 64'hf67abd592d19e38c};
    test_data[46] = {64'h5bbdb69fa7696f26, 64'hf7fd5869cd6fb652};
    test_data[47] = {64'h351175a8bf746925, 64'h1885efc0c6304c91};
    test_data[48] = {64'h104232d4c8202f72, 64'h4696552a109e66c7};
    test_data[49] = {64'h0e6506c016b030ee, 64'hfe83ac58cae86427};
    test_data[50] = {64'h82fecb078312e008, 64'h74f2c4c034fbe5df};
    test_data[51] = {64'h11749d9f1223292f, 64'he16d548e845f01cf};
    test_data[52] = {64'hb9b358ed4e0176be, 64'h7ccace6e81f51cde};
    test_data[53] = {64'h761bff435e87e55e, 64'hc2c105efb2ff4433};
    test_data[54] = {64'h8db744703e892fd8, 64'h8e671e31142a4f2f};
    test_data[55] = {64'h7398ff4444c42819, 64'h200c2b5ffd85bfec};
    test_data[56] = {64'hc74e2fe17486fc55, 64'h253a7e26a8c880d4};
    test_data[57] = {64'h288053a5331a4315, 64'h9267e74245fead5f};
    test_data[58] = {64'h1fb726b1e06317d6, 64'h48a1349da8388d8f};
    test_data[59] = {64'ha95764fb41065a54, 64'h7a7969e978d0bed0};
    test_data[60] = {64'h97580c889d7bb5c6, 64'h61069f094cb1bfa0};
    test_data[61] = {64'h2134cc99e001f61d, 64'h85f64f3183a4ab17};
    test_data[62] = {64'h731d92bad0ebc692, 64'heb756782d8b7cc5d};
    test_data[63] = {64'h1b877b09e33e493c, 64'ha43cccd4c9ca923f};
    // B矩阵数据开始 (64'h5ddc1b2bf2937d7d, 64'he0176594e180367f)
    test_data[64] = {64'h5ddc1b2bf2937d7d, 64'he0176594e180367f};
    test_data[65] = {64'h18b8a6848df1abb3, 64'h0083e2aa6c80447f};
    test_data[66] = {64'h7533cbc490b4babc, 64'h80056d751d80d17f};
    test_data[67] = {64'h16344eef1a0ab68d, 64'hf657f540a8801c7f};
    test_data[68] = {64'h66423873c73e63f1, 64'h1b1d9cdd7780e87f};
    test_data[69] = {64'h7ef744ae32f3f61c, 64'h5e650811cb80c67f};
    test_data[70] = {64'hf35bacd50e438454, 64'h112ccd4ec380ba7f};
    test_data[71] = {64'hd46bb89f1130bfcf, 64'hdcf1fcf3b380e17f};
    test_data[72] = {64'hac6051e8a0447e3a, 64'h8be03a281280d37f};
    test_data[73] = {64'h25b6c109d100b01f, 64'h5942f0886a80a27f};
    test_data[74] = {64'hb005a908d0853e23, 64'h40570873ae80ae7f};
    test_data[75] = {64'hcb467232712ac7b1, 64'h8bf3f0b40780d07f};
    test_data[76] = {64'h9c94d15bcaee29fd, 64'h397a00fe5380007f};
    test_data[77] = {64'h1c8968259f2672d8, 64'h1bedc8bfef80ff7f};
    test_data[78] = {64'hf0f36e6306518f1b, 64'h88e164a0e480927f};
    test_data[79] = {64'h7f2801813e8ed484, 64'hdb0216591d80e77f};
    // A矩阵数据开始 (64'hf53fb6d2e6a85f40, 64'h5c47877939015c55)
    test_data[80] = {64'hf53fb6d2e6a85f40, 64'h5c47877939015c55};
    test_data[81] = {64'h8080808080808080, 64'hc41d5be0e20b2666};
    test_data[82] = {64'ha241416dca400c88, 64'h11f9de99d3dbbb63};
    test_data[83] = {64'h8080808080808080, 64'h931646c2a502507c};
    test_data[84] = {64'hd03b095d6e8e1745, 64'ha4c1c7e66e452d87};
    test_data[85] = {64'hbd924b2883d2ae68, 64'h062021d9dead896b};
    test_data[86] = {64'h6531608b56726dab, 64'h0069bcaf497cf808};
    test_data[87] = {64'h44fd5b7f4b43c83a, 64'h875b86a53153a475};
    test_data[88] = {64'hd7e0fa0c3bbf96b1, 64'hd27460de43bd947b};
    test_data[89] = {64'haaba4d95be5b506b, 64'h71c98550a54dc3de};
    test_data[90] = {64'h632d0d1e6472d012, 64'h0cb5384de43e3b55};
    test_data[91] = {64'h51a64b0044b0a949, 64'ha249e515e3f9e98a};
    test_data[92] = {64'ha518fcf8a024b9ac, 64'h0761700dd916f611};
    test_data[93] = {64'hcce043bf09a8a189, 64'h766c2667818a4cf5};
    
    $display("测试数据已加载，共96个128位数据");
    $display("数据来源：int8.coe文件（每两个64位数据合并为一个128位）");
end

// 测试过程
integer test_count;
reg [7:0] data_index;  // 改为8位以支持96个数据

initial begin
    // 初始化
    reset_n = 0;
    start = 0;
    read_write = 0;
    addr = 0;
    burst_len = 0;
    burst_size = 0;
    burst_type = 0;
    write_data = 0;
    write_data_valid = 0;
    test_count = 0;
    data_index = 0;
    
    // 复位
    #100;
    reset_n = 1;
    #50;
    
    // 开始写测试
    $display("开始AXI写突发传输测试...");
    $display("使用int8.coe文件中的前192个64位数据合并为96个128位数据");
    
    // 配置写参数
    addr = 32'h1000;           // 起始地址
    burst_len = 8'd96;         // 96次突发（128位）
    burst_size = 3'b100;       // 128位 (16字节)
    burst_type = 2'b01;        // INCR突发类型
    read_write = 0;            // 写操作
    
    // 启动传输
    start = 1;
    #10;
    start = 0;
    
    // 发送测试数据
    data_index = 0;
    while (data_index < 96) begin
        if (write_data_ready) begin
            write_data = test_data[data_index];
            write_data_valid = 1;
            data_index = data_index + 1;
            if (data_index % 16 == 0) begin
                $display("已发送 %d 个128位数据", data_index);
            end
        end
        #10;
    end
    write_data_valid = 0;
    
    // 等待传输完成
    wait (done);
    #100;
    
    if (error) begin
        $display("错误：传输失败！");
    end else begin
        $display("成功：96次突发写传输完成！");
        $display("所有数据都来自int8.coe文件（128位格式）");
    end
    
    // 验证写入的数据
    $display("验证写入的数据...");
    for (integer i = 0; i < 96; i = i + 16) begin
        #10;
        $display("地址范围 0x%x-0x%x 包含数据: 0x%032x 到 0x%032x", 
                32'h1000 + i*16, 32'h1000 + (i+15)*16, test_data[i], test_data[i+15]);
    end
    
    $finish;
end

// 监控信号 - 修正后的版本
reg [7:0] write_counter;  // 添加写计数器来跟踪传输进度

always @(posedge clk) begin
    if (!reset_n) begin
        write_counter <= 0;
    end else if (wvalid && wready) begin
        if (wlast) begin
            write_counter <= 0;  // 重置计数器
        end else begin
            write_counter <= write_counter + 1;
        end
    end
end

always @(posedge clk) begin
    if (awvalid && awready) begin
        $display("时间 %0t: AXI写地址 0x%x, 长度 %d", $time, awaddr, awlen);
    end
    
    if (wvalid && wready) begin
        if (write_counter == 0 || write_counter == 95 || wlast) begin
            $display("时间 %0t: AXI写数据 0x%032x, wlast=%b, 计数器=%d", $time, wdata, wlast, write_counter);
        end
    end
    
    if (bvalid && bready) begin
        $display("时间 %0t: AXI写响应完成, bresp=%b", $time, bresp);
    end
end

// 波形输出
initial begin
    $dumpfile("axi_bram_write_test_128bit.vcd");
    $dumpvars(0, axi_bram_write_test_128bit);
end

endmodule